package io.github.wanggit.antrpc.boot;

import io.github.wanggit.antrpc.client.config.DefaultConfigContainer;
import io.github.wanggit.antrpc.client.config.IConfigChangeListener;
import io.github.wanggit.antrpc.client.config.IConfigClient;
import io.github.wanggit.antrpc.client.config.IConfigContainer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

/** 配置AntRpc配置中心的启动时机。 */
@Slf4j
public class AntRpcConfigCenterSpringApplicationRunListener
        implements SpringApplicationRunListener {

    private final SpringApplication springApplication;
    private final String[] args;
    private IConfigContainer configContainer;

    public AntRpcConfigCenterSpringApplicationRunListener(
            SpringApplication springApplication, String[] args) {
        this.springApplication = springApplication;
        this.args = args;
    }

    @Override
    public void starting() {}

    /**
     * Spring 容器环境准备完成之后，启动配置容器，并开启对配置的监听
     *
     * @param environment evn
     */
    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        configContainer = new DefaultConfigContainer(environment);
        try {
            configContainer.start();
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Spring 容器上下文准备成功之后，再把配置容器以单例的形式注入到Spring容器中
     *
     * @param context spring context
     */
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        if (log.isInfoEnabled()) {
            log.info("register " + IConfigClient.class.getName() + " to Spring Container.");
        }
        context.getBeanFactory().registerSingleton(IConfigClient.class.getName(), configContainer);
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {}

    /**
     * 在Spring容器启动完成之后，再把 {@link IConfigChangeListener} 配置变化监听器，添加到配置容器中中.
     *
     * @param context spring context
     */
    @Override
    public void started(ConfigurableApplicationContext context) {
        if (log.isInfoEnabled()) {
            log.info("add all IConfigChangeListener to DefaultConfigContainer.");
        }
        context.getBeansOfType(IConfigChangeListener.class)
                .values()
                .forEach(it -> configContainer.addConfigChangeListener(it));
    }

    @Override
    public void running(ConfigurableApplicationContext context) {}

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {}
}
